package org.fanximall.erp.product.infrastructure.repository;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.fanximall.erp.common.base.BaseDO;
import org.fanximall.erp.common.page.PageResponse;
import org.fanximall.erp.product.domain.aggregate.CategoryAggregateRoot;
import org.fanximall.erp.product.domain.dto.CategoryPageQueryDTO;
import org.fanximall.erp.product.domain.model.ProductCategoryModel;
import org.fanximall.erp.product.domain.model.ProductLeafCategoryModel;
import org.fanximall.erp.product.domain.repository.CategoryRepository;
import org.fanximall.erp.product.infrastructure.builder.CategoryBuilder;
import org.fanximall.erp.product.infrastructure.dao.entity.ProductCategoryDO;
import org.fanximall.erp.product.infrastructure.dao.entity.ProductLeafCategoryDO;
import org.fanximall.erp.product.infrastructure.dao.mapper.ProductCategoryMapper;
import org.fanximall.erp.product.infrastructure.dao.mapper.ProductLeafCategoryMapper;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author :  william
 * @version :  V1.0  created in 2024/4/30
 */
@Repository
public class CategoryRepositoryImpl implements CategoryRepository {

    @Resource
    private ProductCategoryMapper productCategoryMapper;

    @Resource
    private ProductLeafCategoryMapper leafCategoryMapper;

    @Resource
    private CategoryBuilder categoryBuilder;

    @Override
    public void saveCategory(ProductCategoryModel productCategoryModel) {
        productCategoryMapper.insert(categoryBuilder.productCategoryDOBuild(productCategoryModel));
    }

    @Override
    public void saveLeafCategory(ProductLeafCategoryModel productLeafCategoryModel) {
        leafCategoryMapper.insert(categoryBuilder.productLeafCategoryDOBuild(productLeafCategoryModel));
    }

    @Override
    public List<ProductCategoryModel> getAllCategory(Integer state, String name) {
        LambdaQueryWrapper<ProductCategoryDO> queryWrapper = Wrappers.lambdaQuery(ProductCategoryDO.class);
        queryWrapper.eq(ObjectUtils.isNotEmpty(state), ProductCategoryDO::getState, state).eq(StringUtils.isNotBlank(name), ProductCategoryDO::getNameCn, name);
        List<ProductCategoryDO> productCategoryDOS = productCategoryMapper.selectList(queryWrapper);
        return categoryBuilder.productCategoryModelBuildList(productCategoryDOS);
    }

    @Override
    public PageResponse<CategoryAggregateRoot> pageQueryAttributeItem(CategoryPageQueryDTO categoryPageQueryDTO) {
        Page<ProductCategoryDO> page = new Page<>(categoryPageQueryDTO.getCurrent(), categoryPageQueryDTO.getSize());
        LambdaQueryWrapper<ProductCategoryDO> queryWrapper = Wrappers.lambdaQuery(ProductCategoryDO.class);
        queryWrapper.eq(ObjectUtils.isNotEmpty(categoryPageQueryDTO.getState()), ProductCategoryDO::getState, categoryPageQueryDTO.getState()).eq(ObjectUtils.isNotEmpty(categoryPageQueryDTO.getCategoryId()), ProductCategoryDO::getCategoryId, categoryPageQueryDTO.getCategoryId()).like(StringUtils.isNotBlank(categoryPageQueryDTO.getName()), ProductCategoryDO::getNameCn, categoryPageQueryDTO.getName()).orderByAsc(BaseDO::getCreateTime);
        Page<ProductCategoryDO> productConfAttributeItemsPage = productCategoryMapper.selectPage(page, queryWrapper);
        List<ProductCategoryDO> records = productConfAttributeItemsPage.getRecords();
        List<CategoryAggregateRoot> categoryAggregateRoots = new ArrayList<>();
        Map<Long, ProductLeafCategoryDO> productLeafCategoryDOMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(records)) {
            List<Long> leafCategoryList = records.stream().filter(ProductCategoryDO::getLeaf).map(ProductCategoryDO::getCategoryId).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(leafCategoryList)) {
                List<ProductLeafCategoryDO> productLeafCategoryDOS = leafCategoryMapper.selectList(Wrappers.lambdaQuery(ProductLeafCategoryDO.class).in(ProductLeafCategoryDO::getCategoryId, leafCategoryList));
                if (CollectionUtils.isNotEmpty(productLeafCategoryDOS)) {
                    productLeafCategoryDOMap = productLeafCategoryDOS.stream().collect(Collectors.toMap(ProductLeafCategoryDO::getCategoryId, Function.identity()));
                }
            }
            Map<Long, ProductLeafCategoryDO> finalProductLeafCategoryDOMap = productLeafCategoryDOMap;
            categoryAggregateRoots = records.stream().map(item -> {
                ProductLeafCategoryDO leafCategoryDO = finalProductLeafCategoryDOMap.get(item.getCategoryId());
                return CategoryAggregateRoot.builder().productCategoryModel(categoryBuilder.productCategoryModelBuild(item)).productLeafCategoryModel(categoryBuilder.productLeafCategoryModelBuild(leafCategoryDO)).build();

            }).collect(Collectors.toList());
        }
        return new PageResponse<>(productConfAttributeItemsPage.getCurrent(), productConfAttributeItemsPage.getSize(), productConfAttributeItemsPage.getTotal(), categoryAggregateRoots);

    }

    @Override
    public CategoryAggregateRoot getCategoryByCategoryId(Long categoryId) {
        ProductCategoryDO productCategoryDO = productCategoryMapper.selectById(categoryId);
        return CategoryAggregateRoot.builder().productCategoryModel(categoryBuilder.productCategoryModelBuild(productCategoryDO)).productLeafCategoryModel(categoryBuilder.productLeafCategoryModelBuild(leafCategoryMapper.selectById(categoryId))).build();
    }

    @Override
    public void updateLeafCategory(ProductLeafCategoryModel productLeafCategoryModel) {
        leafCategoryMapper.updateById(categoryBuilder.productLeafCategoryDOBuild(productLeafCategoryModel));
    }

    @Override
    public void updateCategory(ProductCategoryModel productCategoryModel) {
        productCategoryMapper.updateById(categoryBuilder.productCategoryDOBuild(productCategoryModel));
    }

    @Override
    public List<ProductCategoryModel> getCategoryByCategoryName(String categoryName, String categoryNameEn) {
        LambdaQueryWrapper<ProductCategoryDO> queryWrapper = Wrappers.lambdaQuery(ProductCategoryDO.class);
        queryWrapper.like(ProductCategoryDO::getNameCn, categoryName).or().like(ProductCategoryDO::getNameEn, categoryNameEn);
        return categoryBuilder.productCategoryModelBuildList(productCategoryMapper.selectList(queryWrapper));
    }


    @Override
    public List<ProductCategoryModel> getAllParent(Long categoryId) {
        List<ProductCategoryDO> parentNodes = new ArrayList<>();
        getParentNode(categoryId, parentNodes);
        return categoryBuilder.productCategoryModelBuildList(parentNodes);
    }

    private void getParentNode(Long categoryId, List<ProductCategoryDO> parentNodes) {
        ProductCategoryDO productCategoryDO = productCategoryMapper.selectById(categoryId);
        if (null != productCategoryDO) {
            Long parentId = productCategoryDO.getParentId();
            parentNodes.add(productCategoryDO);
            if (null == parentId || Objects.equals(0L, parentId)) {
                return;
            }
            getParentNode(parentId, parentNodes);

        }
    }
}
